/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.clazz; import java.util.Map; import java.util.HashMap; import java.util.Collections; import java.lang.ref.SoftReference; import org.openide.util.Task; import org.openide.nodes.Node; import org.openide.loaders.DataObject; import org.openide.loaders.MultiDataObject; import org.openide.src.*; /** The implementation of source element for class objects. * This class is final only for performance reasons, * can be happily unfinaled if desired. * * @author Dafe Simonek, Jan Jancura */ public final class SourceElementImpl extends MemberElementImpl implements SourceElement.Impl { /** Empty array of imports - constant to return fro getImports() */ static final Import[] EMPTY_IMPORTS = new Import[0]; /* Soft reference to the class element */ private SoftReference topClass; /** Soft ref to the map holding all inners */ private SoftReference allClasses; /** The identifier of the package of the class data */ private Identifier packg; /** Association with the class data object (can be null) */ private ClassDataObject cdo; static final long serialVersionUID =-4870331896218546842L; /** Creates object with asociated class and no class data object */ public SourceElementImpl (Class data) { this(data, null); } /** Creates object with asociated class and with asociated * class data object which created this source element (can be null). */ public SourceElementImpl (Class data, ClassDataObject cdo) { super(data); this.cdo = cdo; } /** Not supported. Throws SourceException. */ public void setPackage (Identifier id) throws SourceException { throw new SourceException(); } /** @return The package of class which we are representing. */ public Identifier getPackage () { if (packg == null) { Package pac = ((Class)data).getPackage(); if (pac != null) { packg = Identifier.create(pac.getName()); } } return packg; } /** @return always returns empty array */ public Import[] getImports () { return EMPTY_IMPORTS; } /** Not supported. Throws SourceException. */ public void changeImports (Import[] elems, int action) throws SourceException { throw new SourceException(); } /** Not supported. Throws SourceException. */ public void changeClasses (ClassElement[] elems, int action) throws SourceException { throw new SourceException(); } /** Always returns only one class element which belongs to the * class data we were given in constructor. */ public ClassElement[] getClasses () { return new ClassElement[] { getClassElement() }; } /** Finds an inner class with given name. * @param name the name to look for * @return the element or null if such class does not exist */ public ClassElement getClass (Identifier name) { return (ClassElement)getAllClassesMap ().get(name); } /** @return Top level class which we are asociated with * and all its innerclasses and innerinterfaces. */ public ClassElement[] getAllClasses () { return (ClassElement[])getAllClassesMap ().values().toArray (new ClassElement[0]); } /** @return Always returns STATUS_OK, 'cause we always have the class... */ public int getStatus () { return SourceElement.STATUS_OK; } /** Returns empty task, because we don't need any preparation. */ public Task prepare () { return Task.EMPTY; } /************* utility methods *********/ /** Returns class element for asociated class data. * Care must be taken, 'cause we are playing with soft reference. */ private ClassElement getClassElement () { ClassElement result = (topClass == null) ? null : (ClassElement)topClass.get(); if (result == null) { result = new ClassElement( new ClassElementImpl((Class)data), (SourceElement)element); topClass = new SoftReference(result); } return result; } /** Returns map with all innerclasses. * @return map with all innerclasses. */ private Map getAllClassesMap () { Map allClassesMap = (allClasses == null) ? null : (Map)allClasses.get(); if (allClassesMap == null) { // soft ref null, we must recreate allClassesMap = createClassesMap(); // remember it, please ... allClasses = new SoftReference(allClassesMap); } return allClassesMap; } /** Recursively creates the map of all classes. * The entries in the map are built from * identifier - class element pairs. */ private Map createClassesMap () { Map result = new HashMap(15); addClassElement(result, getClassElement()); return result; } /** Adds given class element to the output map and * recurses on its inner classes and interfaces. */ private void addClassElement (Map map, final ClassElement outer) { map.put(outer.getName(), outer); // recurse on inners ClassElement[] inners = null; try { inners = outer.getClasses(); } catch (Throwable exc) { // rethrow only ThreadDeath, ignore otherwise if (exc instanceof ThreadDeath) throw (ThreadDeath)exc; return; } for (int i = 0; i < inners.length; i++) { addClassElement(map, inners[i]); } } /** Lock the underlaing document to have exclusive access to it and could make changes * on this SourceElement. * * @param run the action to run */ public void runAtomic (Runnable run) { run.run(); } /** Executes given runnable in "user mode" does not allowing any modifications * to parts of text marked as guarded. The actions should be run as "atomic" so * either happen all at once or none at all (if a guarded block should be modified). * * @param run the action to run */ public void runAtomicAsUser (Runnable run) { run.run(); } /** DataObject cookie supported. * @return data object cookie or null */ public Node.Cookie getCookie (Class type) { if (type.equals(DataObject.class) || type.equals(MultiDataObject.class) || ClassDataObject.class.isAssignableFrom(type)) { return cdo; } return null; } public Object readResolve() { return new SourceElement(this); } } /* * Log * 11 src-jtulach1.10 1/20/00 David Simonek #2119 bugfix * 10 src-jtulach1.9 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 9 src-jtulach1.8 9/14/99 David Simonek classes with no package * now supported correctly * 8 src-jtulach1.7 8/9/99 Ian Formanek Generated Serial Version * UID * 7 src-jtulach1.6 7/8/99 Petr Hamernik runAtomic simple * implementation * 6 src-jtulach1.5 6/9/99 Ian Formanek ---- Package Change To * org.openide ---- * 5 src-jtulach1.4 4/1/99 Jan Jancura Object browser support * 4 src-jtulach1.3 3/26/99 David Simonek properties, actions * completed, more robust now * 3 src-jtulach1.2 2/17/99 Petr Hamernik serialization changed. * 2 src-jtulach1.1 2/11/99 David Simonek * 1 src-jtulach1.0 1/29/99 David Simonek * $ */